package com.kitty.game.player;

//import com.kitty.common.cache.RedisDao;

import com.kitty.common.utils.SpringUtils;
import com.kitty.cross.login.service.CrossService;
import com.kitty.game.ServerService;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.equip.service.EquipService;
import com.kitty.game.fuling.model.Fuling;
import com.kitty.game.hunqiao.model.HunQiaoData;
import com.kitty.game.player.model.AccountProfile;
import com.kitty.game.player.model.PlayerProfile;
import com.kitty.game.role.RoleInfo;
import com.kitty.game.role.message.RespExistedRoleList;
import com.kitty.game.role.model.Account;
import com.kitty.game.role.model.AccountLogin;
import com.kitty.game.role.model.Role;
import com.kitty.game.role.service.AccountService;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.FieldUtils;
import com.kitty.mina.cache.SessionUtils;
import com.kitty.mina.message.MessagePusher;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.session.IoSession;
import org.nutz.dao.Cnd;
import org.nutz.dao.Condition;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class PlayerService {

    public static final String CACHE_ROLE_KEY_PREFIX = "role:";

//    @Autowired
//    private RedisDao redisDao;

    @Autowired
    private Dao dao;

    @Autowired
    private JdbcTemplate jdbcTemplate;
    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 全服所有角色的简况
     */
    private ConcurrentMap<Long, PlayerProfile> playerProfiles = new ConcurrentHashMap<>();

    /**
     * 全服所有账号的简况
     */
    private ConcurrentMap<String, AccountProfile> accountProfiles = new ConcurrentHashMap<>();


    /**
     * 名字跟uid的映射
     */
    private ConcurrentHashMap<String, Long> name2roleUid = new ConcurrentHashMap<>();

    /**
     * roleId跟roleUid的影射
     */
    private ConcurrentHashMap<Integer, Long> roleId2roleUid = new ConcurrentHashMap<>();

    private class PlayerRowMapper implements RowMapper<PlayerProfile> {

        @Override
        public PlayerProfile mapRow(ResultSet re, int arg1) throws SQLException {
            return new PlayerProfile(re.getString("sid"), re.getInt("roleId"), re.getLong("uid"), re.getString("name"),
                    re.getString("distName"), re.getShort("roleIcon"),
                    re.getShort("level"),
                    re.getShort("polar"), re.getLong("enterTime"));
        }

    }

    private long getUidByName(String name) {
        String sqlstr = "select uid from t_role where name=@name";
        Sql sql = Sqls.create(sqlstr);
        sql.setParam("name", name);
        sql.setCallback(new SqlCallback() {
            @Override
            public Object invoke(Connection connection, ResultSet resultSet, Sql sql) throws SQLException {
                if (resultSet.next()) {
                    return resultSet.getLong("uid");
                }
                return 0;
            }
        });
        SpringUtils.getBean(Dao.class).execute(sql);
        long uid = sql.getLong();
        return uid;
    }

    public void transRole(Role gm, String content) {
        String[] strings = content.split("##");
        String rolename = strings[0];
        Role role = SpringUtils.getRoleService().getOnlinePlayer(rolename);
        if (role == null) {
            long uid = getUidByName(rolename);
            role = SpringUtils.getRoleService().getPlayerBy(uid);
            if (role == null) {
                MessagePusher.pushMessage(gm, new RespNotifyMiscEx("角色不存在"));
                return;
            }
        }
        IoSession ioSession = SessionUtils.getSession(role.getRoleId());
        if (ioSession != null) {
            ioSession.closeNow();
        }

        AccountProfile account = accountProfiles.get(role.getSid());
        if (account == null) {
            return;
        }
        String accountName = strings[1].trim().replaceAll(" ", "");
        AccountLogin accountLogin = SpringUtils.getBean(AccountService.class).queryByUsername(accountName);
        if (accountLogin == null) {
            logger.error("找不到账号信息=={}", content);
            MessagePusher.pushMessage(gm, new RespNotifyMiscEx("账号#R" + accountName + "#n不存在，不能转移！！"));
            return;
        }
        PlayerProfile oldProfile = null;
        List<PlayerProfile> playerProfiles = account.getPlayers();
        account.setPlayers(new ArrayList<>());
        for (PlayerProfile playerProfile : playerProfiles) {
            if (playerProfile.getName().equals(rolename)) {
                oldProfile = playerProfile;
                continue;
            }
            account.getPlayers().add(playerProfile);
        }
        if (oldProfile == null) {
            for (PlayerProfile playerProfile : playerProfiles) {
                logger.error("找不到角色信息=={}=={}", content, Json.toJson(playerProfile, JsonFormat.compact()));
            }
            logger.error("找不到角色信息=={}=={}", content);
            MessagePusher.pushMessage(gm, new RespNotifyMiscEx("角色异常，不能转移！！"));
            return;
        }
        oldProfile.setSid(accountLogin.getId());
        addPlayerProfile(oldProfile);
        role.setSid(accountLogin.getId());
        role.save();
    }


    public void delProfile(String accountId, String name) {
        AccountProfile account = accountProfiles.get(accountId);
        if (account == null) {
            return;
        }
        List<PlayerProfile> playerProfiles = account.getPlayers();
        account.setPlayers(new ArrayList<>());
        for (PlayerProfile playerProfile : playerProfiles) {
            if (playerProfile.getName().equals(name)) {
                continue;
            }
            account.getPlayers().add(playerProfile);
        }
    }

    private AtomicInteger randNameInc = new AtomicInteger();

    public int getPlayerCount() {
        String sql = "select count(*) from t_role";
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        return count;
    }

    public void loadAllPlayerProfiles() {
        playerProfiles.clear();
        accountProfiles.clear();
        name2roleUid.clear();
        String sql = "select sid, roleId, uid, `name`, distName, roleIcon, `level`, polar,enterTime from t_role";
        List<PlayerProfile> profileList = jdbcTemplate.query(sql, new PlayerRowMapper());
        logger.error("玩家数量=={}", profileList.size());
        profileList.forEach(p -> {
            if (name2roleUid.containsKey(p.getName())) {
                if (SpringUtils.getBean(ServerService.class).getServer().getId() != 10000) {
                    String oldName = p.getName();
                    p.setName(p.getName() + randNameInc.getAndIncrement());
                    log.error("玩家{}自动从{}改名为{}", p.getRoleId(), oldName, p.getName());
                    Role role = SpringUtils.getPlayerService().getPlayerBy(p.getGid());
                    role.setName(p.getName());
                    try {
                        SpringUtils.getBean(EquipService.class).addMall("改头换面卡", true, role, 1);
                    } catch (Exception e) {
                        log.error("", e);
                    }
                    role.save();
                }
            }
            addPlayerProfile(p);
        });
    }

    public ConcurrentMap<Long, PlayerProfile> getAllPlayerProfiles() {
        return playerProfiles;
    }

    public void addPlayerProfile(PlayerProfile baseInfo) {
        playerProfiles.put(baseInfo.getGid(), baseInfo);

        String accountId = baseInfo.getSid();
        AccountProfile accountProfile = null;
        if (!accountProfiles.containsKey(baseInfo.getSid())) {
            // 必须将account加载并缓存
            accountProfile = new AccountProfile();
            accountProfile.setPlayers(new ArrayList<>());
            accountProfiles.putIfAbsent(accountId, accountProfile);
        } else {
            accountProfile = accountProfiles.get(baseInfo.getSid());
        }

        accountProfile.getPlayers().add(baseInfo);

        name2roleUid.put(baseInfo.getName(), baseInfo.getGid());
        roleId2roleUid.put(baseInfo.getRoleId(), baseInfo.getGid());
    }


    /**
     * 发送角色列表
     *
     * @param sid
     * @param serverName
     * @param session
     */
    public List<RoleInfo> listRoleInfos(String sid, String serverName, IoSession session) {
        List<RoleInfo> list = new ArrayList<>();
        List<PlayerProfile> playerProfiles = getPlayersBy(sid);
        playerProfiles.stream().filter(p -> p.getDistName().equals(serverName)).forEach(p -> {
            //     这个是不弹新手战斗     直接进入游戏     两个都可以用
            RoleInfo roleInfo = new RoleInfo();
            // 【重要】关闭开场战斗，如果是新手就关闭开场动画
            if (roleInfo.getLast_login_time() == 0)
                roleInfo.setLast_login_time(1);
            else
                roleInfo.setLast_login_time((int) p.getEnterTime());
            // mod:e
            byte onlineStatus = 0;
            if (SpringUtils.getRoleService().isOnline(p.getGid())) {
                onlineStatus = 1;
            }
            roleInfo.setList(FieldUtils.roleInfo(p, onlineStatus));
            list.add(roleInfo);
            //这个是弹出界面是否跳过新手战斗
//                RoleInfo roleInfo = new RoleInfo();
//                  roleInfo.setLast_login_time((int) p.getEnterTime());
//                   byte onlineStatus = Const.CHAR_LIST_T_NONE;
//                    if (SpringUtils.getRoleService().isOnline(p.getGid())) {
//                        onlineStatus = Const.CHAR_LIST_T_ONLINE;
//                    }
//                    roleInfo.setList(FieldUtils.roleInfo(p, onlineStatus));
//                    list.add(roleInfo);
        });
        if (session != null) {
            RespExistedRoleList respExistedRoleList = new RespExistedRoleList();
            respExistedRoleList.setOpenServerTime(new Long(System.currentTimeMillis() / 1000).intValue());
            respExistedRoleList.setList(list);
            respExistedRoleList.setAccount_online(Const.CHAR_LIST_T_ONLINE);//在线
            respExistedRoleList.setAccount_online(Const.CHAR_LIST_T_NONE);//不在线
            MessagePusher.pushMessage(session, respExistedRoleList);
        }
        return list;
    }

    // add Tao 删除角色
    public void deleteRole(Role role) {
        if (role == null) {
            this.logger.error("角色不存在=={}=={}");
            return;
        }
        this.delProfile(role.getSid(), role.getName());
        Account account = SpringUtils.getAccountService().getAccount(role.getSid());
        if (account != null && account.getPrivilege() >= 200) return;
        IoSession session = SessionUtils.getSession(role.getRoleId());
        if (session != null) {
            session.closeNow();
        }
        role.setDelete(true);
        role.save();
        this.logger.error("删除角色=={}=={}", role.getRoleId(), role.getName());
    }
    // add:e

    public void delKuafuRole() {
        loadAllPlayerProfiles();
        ArrayList<Long> arrayList = new ArrayList(roleId2roleUid.values());
        logger.error("删除角色数量=={}=={}", roleId2roleUid.size(), name2roleUid.size());
        logger.error("删除角色数量=={}=={}", Json.toJson(name2roleUid, JsonFormat.compact()));
        for (long uid : arrayList) {
            Role role = SpringUtils.getPlayerService().getPlayerBy(uid);
            if (role == null) {
                logger.error("角色不存在=={}=={}");
                continue;
            }
            delProfile(role.getSid(), role.getName());
            Account account = SpringUtils.getAccountService().getAccount(role.getSid());
            if (account != null && account.getPrivilege() >= 200) {
                continue;
            }
            IoSession session = SessionUtils.getSession(role.getRoleId());
            if (session != null) {
                session.closeNow();
            }
            role.setDelete(true);
            role.save();
            logger.error("删除角色=={}=={}", role.getRoleId(), role.getName());
//            SpringUtils.getBean(PlayerService.class).del(role);
        }
        List<Fuling> query = dao.query(Fuling.class, (Condition) Cnd.NEW());
        for (Fuling fuling : query) {
            dao.delete(fuling);
        }
        List<HunQiaoData> query1 = dao.query(HunQiaoData.class, Cnd.NEW());
        dao.delete(query1);
    }

//    @CacheEvict(value="player", allEntries=true)
//    public void del(Role role){
//        role.save();
//    }

    //    public AccountProfile getAccountProfiles(long accountId) {
//        AccountProfile accountProfile = accountProfiles.get(accountId);
//        if (accountProfile != null) {
//            return accountProfile;
//        }
//        Account account = AccountManager.getInstance().get(accountId);
//        if (account != null) {
//            accountProfile = new AccountProfile();
//            accountProfile.setAccountId(accountId);
//            accountProfiles.putIfAbsent(accountId, accountProfile);
//        }
//        return accountProfile;
//    }
//
    public void addAccountProfile(Account account) {
        String accountId = account.getId();
        if (accountProfiles.containsKey(accountId)) {
            throw new RuntimeException("账号重复-->" + accountId);
        }
        AccountProfile accountProfile = new AccountProfile();
        accountProfile.setSid(accountId);
        accountProfiles.put(accountId, accountProfile);
    }

    public List<PlayerProfile> getPlayersBy(String accountId) {
        AccountProfile account = accountProfiles.get(accountId);
        if (account == null) {
            return new ArrayList<>();
        }
        return account.getPlayers();
    }

    @Cacheable(value = "player", key = "#uid")
    public Role getPlayerBy(long uid) {
        if (uid <= 0) {
            return null;
        }
        // 跨服玩家
        Role cPlayer = SpringUtils.getBean(CrossService.class).getCrossPlayer(uid);
        if (cPlayer != null) {
            return cPlayer;
        }
        Role role = dao.fetch(Role.class, Cnd.where("uid", "=", uid));
        if (role != null) {
            role.doAfterInit();
        }
        return role;
    }

    @CachePut(value = "player", key = "#role.uid")
    public Role saveToCache(Role role) {
        return role;
    }

    public long getUidBy(String name) {
        return name2roleUid.getOrDefault(name, 0L);
    }

    /**
     * 通过模糊名字获取id列表
     *
     * @param name
     */
    public List<Long> getUidsByIndistinct(String name) {
        List<Long> result = new ArrayList<>();
        for (Map.Entry<String, Long> entry : name2roleUid.entrySet()) {
            if (entry.getKey().indexOf(name) >= 0) {
                result.add(entry.getValue());
            }
        }

        return result;
    }

    public long getUidBy(int roleId) {
        return roleId2roleUid.getOrDefault(roleId, 0L);
    }


    /**
     * 更新PlayerProfile中等级
     */
    public void updateRoleLevel(Role role) {
        PlayerProfile playerProfile = playerProfiles.get(role.getUid());
        if (playerProfile == null) {
            return;
        }
        playerProfile.setLevel(role.getLevel());
        if(role.getLevel()>=120){
            role.getChildInfo().setUpgradeTotal(role.getChildInfo().getUpgradeTotal() + 1);
            role.getChildInfo().setXian(role.getChildInfo().getXian() + 1);
            role.getChildInfo().setMo(role.getChildInfo().getMo() + 1);
        }
    }

    /**
     * 更新PlayerProfile中进入游戏的时间
     */
    public void updateRoleEnterTime(Role role) {
        PlayerProfile playerProfile = playerProfiles.get(role.getUid());
        if (playerProfile == null) {
            return;
        }

        playerProfile.setEnterTime(role.getEnterTime());
    }

    /**
     * 更新PlayerProfile中Icon 改名之后调用
     */
    public void updateRoleIcon(Role role) {
        PlayerProfile playerProfile = playerProfiles.get(role.getUid());
        if (playerProfile == null) {
            return;
        }

        playerProfile.setRoleIcon(role.getRoleIcon());
    }

    /**
     * 更新PlayerProfile中的角色名  改名之后调用
     */
    public void updateRoleName(String oldName, Role role) {
        PlayerProfile playerProfile = playerProfiles.get(role.getUid());
        if (playerProfile == null) {
            return;
        }
        name2roleUid.remove(oldName);
        name2roleUid.put(role.getName(), role.getUid());
        playerProfile.setName(role.getName());
    }

    public PlayerProfile queryPlayerProfile(long playerId) {
        return playerProfiles.get(playerId);
    }

    public boolean occupyName(String roleName, long uid) {
        return name2roleUid.putIfAbsent(roleName, uid) == null;
    }

    public ArrayList<Long> allUids() {
        return new ArrayList<>(name2roleUid.values());
    }

    public void updatePlayerProfile(Role role) {
        if (role == null) {
            return;
        }
        PlayerProfile playerProfile = playerProfiles.get(role.getUid());
        if (playerProfile == null) {
            return;
        }
        playerProfile.setLevel(role.getLevel());
        playerProfile.setWeaponIcon(role.getWeaponIcon());
        playerProfile.setPartyName(role.getPartyName());
        playerProfile.setCurrTitle(role.getCurrTitle());
        playerProfile.setTao(role.getTao());
        playerProfile.setGender(role.getGender());
        if (SpringUtils.getRoleService().isOpenSet(role, "refuse_stranger_msg")) {
            role.getFriendBox().getStrangerLevel();
        }
        short strangerLevel = SpringUtils.getRoleService().isOpenSet(role, "refuse_stranger_msg") ? role.getFriendBox()
                .getStrangerLevel() : 0;
        playerProfile.setStrangerLevel(strangerLevel);
    }
}